<?php

/**
 * @author      Nguyen Duc Thuan <me@ndthuan.com>
 * @copyright   Copyright (c) 2009 Nguyen Duc Thuan <me@ndthuan.com>
 * @version     $Id: Table.php 12 2009-11-03 03:17:46Z thuan.nguyen $
 */

class Fete_Db_Table
{
    protected $_name = null;

    protected $_dataSetClassName = 'Fete_Model_DataSet';
    
    /**
     *
     * @var Fete_Db
     */
    static protected $_defaultDb = null;

    /**
     *
     * @var Fete_Db
     */
    protected $_db = null;

    /**
     *
     * @param string|array $params
     * @param Fete_Model_DataSet $dataSet
     * @return Fete_Model_DataSet
     */
    public function fetch($params = array(), Fete_Model_DataSet $dataSet = null)
    {
        $db = $this->getDb();
        
        $defaults = array(
            'pn' => 1,
            'pp' => -1,
            'sort' => array(),
            'where' => array(),
            'fields' => '*'
        );

        if (is_string($params)) {
            parse_str($params, $params);
        }
        
        $defaults = array_merge($defaults, $params);

        $conditions = $db->buildWhere($defaults['where']);

        $numOfRows = (integer) $db->getValue(sprintf('SELECT COUNT(*)
            FROM %s %s', $this->_name, $conditions));

        if (-1 == $defaults['pp']) {
            $defaults['pp'] = $numOfRows;
        }

        if (0 == $numOfRows) {
            $numOfPages = 1;
        } else {
            $numOfPages = ceil($numOfRows/$defaults['pp']);
        }

        if ($defaults['pn'] < 1) {
            $defaults['pn'] = 1;
        }

        if ($defaults['pn'] > $numOfPages) {
            $defaults['pn'] = $numOfPages;
        }

        $rows = $db->getAll(sprintf('SELECT %s FROM %s %s LIMIT %d, %d %s',
            $defaults['fields'], $this->_name, $conditions,
            ($defaults['pn']-1)*$defaults['pp'], $defaults['pp'],
            $db->buildSort($defaults['sort'])), MYSQL_ASSOC);

        if (null === $dataSet) {
            $dataSet = new $this->_dataSetClassName;
        }

        return $dataSet->setRawRows($rows)
        ->setNumOfPages($numOfPages)
        ->setNumOfRows($numOfRows)
        ->setPageNum($defaults['pn']);
    }

    /**
     *
     * @param string $field
     * @param string|array $where
     * @return string
     */
    public function getValue($field, $where)
    {
        return $this->getDb()->getValue(sprintf('SELECT %s FROM %s %s',
            $field, $this->_name, $this->getDb()->buildWhere($where)));
    }

    /**
     *
     * @param string $field
     * @param string|array $where
     * @return array
     */
    public function getValues($field, $where)
    {
        return $this->getDb()->getValues(sprintf('SELECT %s FROM %s %s',
            $field, $this->_name, $this->getDb()->buildWhere($where)));
    }

    /**
     *
     * @param array|string $where
     * @return integer
     */
    public function delete($where)
    {
        return $this->getDb()->delete($this->_name, $where)->getAffectedRows();
    }

    /**
     *
     * @param Fete_Model_DataRow|array $data
     * @param array|string $where
     * @return integer
     */
    public function update($data, $where = array())
    {
        if ($data instanceof Fete_Model_DataRow) {
            $data = $data->getValues();
        }

        return $this->getDb()->update($this->_name, $data, $where)
        ->getAffectedRows();
    }

    /**
     *
     * @param Fete_Model_DataRow|array $data
     * @param bool $replace
     * @return integer
     */
    public function insert($data, $replace = false)
    {
        if ($data instanceof Fete_Model_DataRow) {
            $data = $data->getValues();
        }

        return $this->getDb()->insert($this->_name, $data, $replace)
        ->getInsertId();
    }

    /**
     *
     * @return Fete_Db
     */
    public function &getDb()
    {
        if (null !== $this->_db) {
            return $this->_db;
        } elseif (null !== self::$_defaultDb) {
            $this->_db = self::$_defaultDb;
            return self::$_defaultDb;
        }

        throw new Fete_Db_Table_Exception(
            'There is no db connection for this class');
        return null;
    }

    /**
     *
     * @param Fete_Db $db
     * @return Fete_Db_Table
     */
    public function &setDb(Fete_Db $db)
    {
        $this->_db = $db;
        return $this;
    }

    /**
     *
     * @param Fete_Db $db 
     */
    static public function setDefaultDb(Fete_Db $db)
    {
        self::$_defaultDb = $db;
    }

    /**
     *
     * @param string $name
     * @return Fete_Db_Table
     */
    public function &setName($name)
    {
        $this->_name = $name;
        return $this;
    }

    /**
     *
     * @param string $name
     * @return Fete_Db_Table
     */
    public function &setDataSetClassName($name)
    {
        $this->_dataSetClassName = $name;
        return $this;
    }

    public function init() {}

    public function __construct($name = null)
    {
        if (null !== $name) {
            $this->_name = $name;
        }

        $this->init();
    }
}